#ifndef __M_QUEUE_H__
#define __M_QUEUE_H__
#include "../mqCommon/logger.hpp"
#include "../mqCommon/helper.hpp"
#include "../mqCommon/mq_msg.pb.h"
#include <iostream>
#include <memory>
#include <mutex>
#include <unordered_map>

namespace yqx{
    //消息队列类
    struct MsgQueue{
        using ptr = std::shared_ptr<MsgQueue>;
        std::string _name;
        bool _durable;
        bool _exclusive;
        bool _auto_delete;

        MsgQueue(const std::string name = "", bool durable = false, bool exclusive = false, bool auto_delete = true)
        :_name(name), _durable(durable), _exclusive(exclusive), _auto_delete(auto_delete){}
    };
    //消息队列数据持久化类
    using QueueMap = std::unordered_map<std::string, MsgQueue::ptr>;
    class MsgQueueMapper{
        public:
            MsgQueueMapper(const std::string& dbfile):_sh(dbfile){
                std::string parentPath = FileHelper::getParentDirectory(dbfile);
                FileHelper::createDirectory(parentPath);
                assert(_sh.open());
                createTable();
            }
            //创建表
            void createTable(){
                #define CREATE_QUEUE_TABLE "create table if not exists queue_table(name varchar(32) primary key, durable int, exclusive int, auto_delete int);"
                bool ret = _sh.exec(CREATE_QUEUE_TABLE, nullptr, nullptr);
                if(ret == false){
                    LOG("创建消息队列数据库表失败！");
                    abort();
                }
            }
            //删除表
            void removeTable(){
                #define DROP_QUEUE_TABLE "drop table if exists exchange_table;"
                bool ret = _sh.exec(DROP_QUEUE_TABLE, nullptr, nullptr);
                if(ret == false){
                    LOG("删除消息队列数据库表失败！");
                    abort();
                }
            }
            //向表中加入一个消息队列数据
            bool insert(MsgQueue::ptr& pqueue){
                std::stringstream ss;
                ss << "insert into queue_table values(";
                ss << "'" << pqueue->_name << "', ";
                ss << pqueue->_durable << ", ";
                ss << pqueue->_exclusive << ", ";
                ss << pqueue->_auto_delete << ");";
                return _sh.exec(ss.str(), nullptr, nullptr);
            }
             //删除一个表中消息队列数据
            bool remove(const std::string name){
                std::stringstream ss;
                ss << "delete from queue_table where name=";
                ss << "'" << name <<"';";
                return _sh.exec(ss.str(), nullptr, nullptr);
            }
            //获得表中所有消息队列数据
            QueueMap recovery(){
                QueueMap res;
                std::string sql = "select name, durable, exclusive, auto_delete from queue_table;";
                _sh.exec(sql, selectCallback, &res);
                return res;
            }
        private:
            static int selectCallback(void* arg, int numcol, char** row, char** fields){
                QueueMap* res = (QueueMap*)arg;
                auto mqp = std::make_shared<MsgQueue>();
                mqp->_name = row[0];
                mqp->_durable = (bool)std::stoi(row[1]);
                mqp->_exclusive = (bool)std::stoi(row[2]);
                mqp->_auto_delete = (bool)std::stoi(row[3]);
                res->insert(std::make_pair(mqp->_name, mqp));
                return 0;
            }
        private:
            SqliteHelper _sh;

    };
    //消息队列数据管理类
    class MsgQueueManager{
        public:
            using ptr = std::shared_ptr<MsgQueueManager>;
            MsgQueueManager(const std::string& dbfile):_mapper(dbfile){
                _msg_queues = _mapper.recovery();
            }
            //声明（创建）消息队列
            bool declareQueue(const std::string& name, bool durable, bool exclusive, bool auto_delete){
                bool res = true;
                std::unique_lock<std::mutex> lock(_mtx);
                auto it = _msg_queues.find(name);
                if(it != _msg_queues.end()){
                    return true;
                }
                auto msp = std::make_shared<MsgQueue>(name, durable, exclusive, auto_delete);
                if(durable)
                    res = _mapper.insert(msp);
                _msg_queues[name] = msp;
                return res;

            }
            //删除一个消息队列
            bool deleteQueue(const std::string& name){
                bool res = true;
                std::unique_lock<std::mutex> lock(_mtx);
                auto it = _msg_queues.find(name);
                if(it == _msg_queues.end()){
                    return true;
                }
                if(it->second->_durable)
                    res = _mapper.remove(name);
                _msg_queues.erase(name);
                return res;
            }
            //获取一个指定队列
            MsgQueue::ptr selectQueue(const std::string& name){
                std::unique_lock<std::mutex> lock(_mtx);
                auto it = _msg_queues.find(name);
                if(it == _msg_queues.end()){
                    return nullptr;
                }
                return it->second;
            }
            //获取所有的队列信息
            QueueMap getAllQueues(){
                std::unique_lock<std::mutex> lock(_mtx);
                return _msg_queues;
            }
            //判断一个队列是否存在
            bool exists(const std::string& name){
                std::unique_lock<std::mutex> lock(_mtx);
                auto it = _msg_queues.find(name);
                if(it == _msg_queues.end()){
                    return false;
                }
                return true;
            }
            //删除所有队列
            void clear(){
                std::unique_lock<std::mutex> lock(_mtx);
                _mapper.removeTable();
                _msg_queues.clear();
            }

        private:
            std::mutex _mtx;
            MsgQueueMapper _mapper;
            QueueMap _msg_queues;
    };
}
#endif